﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Npgsql;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
using System.Text.RegularExpressions;


namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {

        NpgsqlConnection cn = new NpgsqlConnection(Conn.connStr);
        NpgsqlCommand cmd = new NpgsqlCommand();
        NpgsqlDataReader dr;
        
        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.Session["usern"] == null || this.Session["passn"] == null)
            {
                Response.Redirect("Default.aspx"); //Om man inte är inloggad hoppar man till förstasidan.
            }
            else
            {
                cmd.Connection = cn;

                cmd.Parameters.AddWithValue("@first_name", this.First_name.Text); //Sparar alla värden i textboxar samt sessions för senare användning
                cmd.Parameters.AddWithValue("@last_name", this.Last_name.Text);
                cmd.Parameters.AddWithValue("@golf_id", this.Session["usern"].ToString());
                cmd.Parameters.AddWithValue("@password", this.Session["passn"].ToString());
                cmd.Parameters.AddWithValue("@phone", this.Phone.Text);
                cmd.Parameters.AddWithValue("@e_mail", this.E_mail.Text);
                cmd.Parameters.AddWithValue("@handicap", this.Handicap.Text);
                                
                if (First_name.Text == "") //Ifall textboxarna är tomma hämtas medlemsinformationen
                {
                    loadboxes();
                    loadtvl();
                    loadkommandetvl();
                    welcome.Text = "Välkommen " + First_name.Text + " dagens datum/tid är " + DateTime.Now; //Skriver ut välkomstmeddelande till den inloggade medlemmen
                }
                if (!Page.IsPostBack)
                {
                    LaddaBokadeTider();
                }
            }
        }

        private void LaddaBokadeTider()
        {
            BokadeTider.Items.Clear();
            List<DateTime> bokade = GetBookedTimes();
            foreach (DateTime tid in bokade) 
            {
                if (tid > DateTime.Now)
                {
                    BokadeTider.Items.Add(new ListItem(tid.ToShortDateString() + " - " + tid.ToShortTimeString()));
                }
            }
        }

        private void loadboxes() //Ser till att alla textboxar är tomm och fyller på med medlemsinformationen
        {
            First_name.Text = "";
            Last_name.Text = "";
            Phone.Text = "";
            E_mail.Text = "";
            Handicap.Text = "";
                                    
            cn.Open();
            cmd.CommandText = "select first_name, last_name, phone, e_mail, handicap from members where golf_id = '" + Session["usern"].ToString() + "'";
            dr = cmd.ExecuteReader();
            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    First_name.Text = dr["first_name"].ToString();
                    Last_name.Text = dr["last_name"].ToString();
                    Phone.Text = dr["phone"].ToString();
                    E_mail.Text = dr["e_mail"].ToString();
                    Handicap.Text = dr["handicap"].ToString();
                }
            }
            cn.Close();
        }


        protected void Update_user_Click1(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("Vill du uppdatera din profil", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question); //En messegebox skapas för att ge medlemen två val
            if (dr == DialogResult.Yes)
            {
                if (newPasswordBox.Text.Length <= 0) //Ifall lösenordsfältet är tomt uppdateras medlemmen med sitt tidigare lösenord
                {
                    cn.Open();
                    cmd.CommandText = "update members set first_name = @first_name, last_name = @last_name, phone= @phone, e_mail = @e_mail, handicap = @handicap, password = @password where golf_id = @golf_id";
                    int antalposter = cmd.ExecuteNonQuery();
                    if (antalposter >= 1)
                    {
                        MessageBox.Show("Din profil är uppdaterad");
                    }
                    else
                    {
                        MessageBox.Show("Det gick inte att uppdatera din profil");
                    }
                    cn.Close();
                    loadboxes();
                }
                else //Uppdaterar medlemmen med nytt lösenord + det andra
                {
                    cn.Open();
                    cmd.CommandText = "update members set first_name = @first_name, last_name = @last_name, phone= @phone, e_mail = @e_mail, handicap = @handicap, password = @newPassword where golf_id = @golf_id";
                    cmd.Parameters.AddWithValue("@newPassword", newPasswordBox.Text);
                    int antalposter = cmd.ExecuteNonQuery();
                    if (antalposter >= 1)
                    {
                        MessageBox.Show("Din profil är uppdaterad");
                    }
                    else
                    {
                        MessageBox.Show("Det gick inte att uppdatera din profil");
                    }
                    cn.Close();
                    loadboxes();
                }
            }
            else if (dr == DialogResult.No) //Avslutar funktionen ifall medlemmen väljer nej
                    {
                        return;
                    }
            }
        

        private void loadtvl() //Hämtar upp alla tävlingar som medlemmen är anmäld till och inte har startat
        {
            DateTime tid = DateTime.Now;
            var today = tid.ToShortDateString();
            cmd.Parameters.AddWithValue("@todayDate", today);
            
            cn.Open();
            cmd.CommandText = "SELECT booking_competition.id, UPPER(competitions.name) namn, TO_CHAR(competitions.start_date, 'dd mon yyyy') startdatum, TO_CHAR(competitions.end_date, 'dd mon yyyy') slutdatum from booking_competition, competitions, members WHERE booking_competition.player = members.golf_id AND booking_competition.competition = competitions.id AND members.golf_id = @golf_id AND competitions.start_date >= @todayDate";
            GridView1.DataSource = LoadGrid();
            GridView1.DataBind();
            cn.Close();
        }

        private void loadkommandetvl() //Hämtar upp alla tävlingar som medlemmen inte är anmäld till och inte har startat
        {
            DateTime tid = DateTime.Now;
            var today = tid.ToShortDateString();
            cmd.Parameters.AddWithValue("@todayDate", today);
            
            cn.Open();
            cmd.CommandText = "SELECT id, UPPER(competitions.name) namn, TO_CHAR(start_date, 'dd mon yyyy') startdatum, TO_CHAR(end_date, 'dd mon yyyy') slutdatum FROM competitions WHERE competitions.id not in (SELECT competition FROM booking_competition WHERE booking_competition.player = @golf_id) AND competitions.start_date >= @todayDate";
            GridView2.DataSource = LoadGrid(); //Skapa en tabell genom att binda (Databind) den hämtade datan via funktionen loadgrid 
            GridView2.DataBind();
            cn.Close();
        }
       
        protected List<DateTime> GetBookedTimes()
        {
            cn.Open();
            
            // Hämta alla spelarens bokade tider
            String sql = String.Format(@"SELECT timestamp,date
                                        FROM booking_play WHERE player='{0}' ORDER BY date DESC",
                                        this.Session["usern"].ToString());
            NpgsqlCommand cmd = new NpgsqlCommand(sql, cn);
            NpgsqlDataReader dr = cmd.ExecuteReader();

            // Lägg alla datum och tider i en DateTime -lista
            List<DateTime> bokade = new List<DateTime>();

            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    // Slå ihop värdet i datum-kolumnen med värdet i tids-kolumnen 
                    DateTime tiden = DateTime.Parse(dr["timestamp"].ToString());
                    bokade.Add(DateTime.Parse(dr["date"].ToString()).Add(TimeSpan.Parse(tiden.ToShortTimeString())));
                }
            }
            cn.Close();
            // returnera DateTime- listan
            return bokade;
        }

        protected void HideSällskap()
        {
            Sällskap1.Items.Clear();
            Sällskap1.Visible = false;
            Sällskap2.Items.Clear();
            Sällskap2.Visible = false;
            Sällskap3.Items.Clear();
            Sällskap3.Visible = false;
            SällskapLabel.Visible = false;
            bokasällskap.Visible = false;
        }

        protected void Datum_SelectionChanged(object sender, EventArgs e)
        {
            HideSällskap();
            sällskapsinfo.Text = "";
            String datestring = Datum.SelectedDate.ToShortDateString();

            // Hämta tider som användaren har bokat
            List<DateTime> bokade = GetBookedTimes();

            // Stoppa alla upptagna tider i en lista som vi kollar mot senare
            List<String> upptagna = new List<string>();
            foreach (DateTime tid in bokade)
            {
                // Stoppa in bokade tider som användaren gjort på det valda datumet
                if (tid.ToShortDateString() == datestring)
                    upptagna.Add(tid.ToShortTimeString());
            }

            // Hämta ut tider som är bokade 4 eller fler gånger
            cn.Open();
            String sql = String.Format(@"SELECT timestamp
                                        FROM booking_play WHERE date='{0}'
                                        GROUP BY timestamp
                                        HAVING COUNT (*) > 4", datestring);
            NpgsqlCommand cmd = new NpgsqlCommand(sql, cn);
            NpgsqlDataReader dr = cmd.ExecuteReader();

            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    // Lägg in tider som är upptagna (4 bokningar eller fler) i listan över upptagna tider
                    upptagna.Add(DateTime.Parse(dr["timestamp"].ToString()).ToShortTimeString());
                    test.Text = DateTime.Parse(dr["timestamp"].ToString()).ToShortTimeString();
                }

            }
            Tider.Items.Clear();
            
            // Lägg till 8 timmar på det valda datumet för att komma till första tiden (08:00)
            DateTime date = DateTime.Parse(datestring).AddHours(8);
            // Denna använder vi för att loopa över alla bokbara tider på datumet
            DateTime currenttime = date;

            // Loopa över alla tider på det valda datumet (ett var 8:e minut)
            while (currenttime < date.AddHours(8))
            {
                // Kolla att tiden inte är med i upptagen-listan
                if (!upptagna.Contains(currenttime.ToShortTimeString()))
                {
                    // Lägg till tiden i drop-down listan
                    Tider.Items.Add(new ListItem(currenttime.ToString()));
                }
                // Nästa tid i loopen
                currenttime = currenttime.AddMinutes(8);
            }

            // Visa drop-downen och boka-knappen
            Tider.Visible = true;
            bokaspel.Visible = true;
            cn.Close();
        }

        public DataTable LoadGrid()
        {
            DataTable table = new DataTable(); //Skapar en ny tabell
            table.Clear();                      //Ser till att tabellen är tom innan proceduren börjar
            try
            {
                NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(cmd); //Skapar en adapter för att kunna fylla tabellen med data
                adapter.Fill(table);  //Fyller tabellen med data
            }
            catch (Exception e)
            {
                MessageBox.Show("Gick inte att hämta data" + e.Message);
            }
            finally  //Behövs inte, men låtit den stå kvar..../Björn
            {
            }
            return table;
        }

        protected bool bokaSpelFörSpelare(string golf_id, string tidStr)
        {
            if (tidStr == "" || golf_id == "")
                return false;
            cn.Open();
            // Hämta ut tiden från den markerade tiden i drop-downen
            DateTime tid = DateTime.Parse(tidStr);

            // Separera tid och datum till två strängar som vi använder till SQL-frågan
            string date = tid.ToShortDateString();
            string timestamp = tid.ToShortTimeString();

            string sql = String.Format(@"INSERT INTO booking_play(
                        time, date, last_update, player, timestamp)
                        VALUES ({0},'{1}','{2}','{3}','{4}')",
                        1, date, DateTime.Now.ToString(), golf_id,
                        timestamp);

            NpgsqlCommand command = new NpgsqlCommand(sql, cn);
            int antalposter = command.ExecuteNonQuery();
            cn.Close();
            if (antalposter != 1) //Eventuella meddelanden vid misslyckad eller lyckad bokning
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        
        protected void bokaspel_Click(object sender, EventArgs e)
        {
            if (bokaSpelFörSpelare(this.Session["usern"].ToString(), Tider.SelectedItem.ToString()))
            {
                // Ta bort den bokade tiden från drop-downen
                test.Text = "Bokade tiden ";
                senastBokadTid.Text = Tider.SelectedItem.ToString();
                Tider.Items.Remove(Tider.SelectedItem);
                LaddaBokadeTider();
                UppdateraSällskapsListor();
            }
            else
            {
                test.Text = "Gick ej att boka tiden " + Tider.SelectedItem.ToString() + "!";
                senastBokadTid.Text = "";
            }
        }

        protected void UppdateraSällskapsListor()
        {
            if (senastBokadTid.Text == "")
                return;
            List<DropDownList> SällskapDropDowns = new List<DropDownList>();
            SällskapDropDowns.Add(Sällskap1);
            SällskapDropDowns.Add(Sällskap2);
            SällskapDropDowns.Add(Sällskap3);
            HideSällskap();

            // Hämta ut hur många lediga platser som finns på tiden och visa så många sällskaps
            // drop-down-boxar som möjligt
            int lediga = 4 - GetBookingCount(senastBokadTid.Text);
            if (lediga > 0)
            {
                SällskapLabel.Visible = true;
                bokasällskap.Visible = true;
                List<String> Användare = GetOtherUsersNotBookedOnTime(senastBokadTid.Text);
                for (int i = 0; i < lediga; i++)
                {
                    SällskapDropDowns[i].Items.Clear();
                    SällskapDropDowns[i].Visible = true;
                    SällskapDropDowns[i].Items.Add(new ListItem("Ingen vald"));
                    foreach (string golf_id in Användare)
                        SällskapDropDowns[i].Items.Add(new ListItem(golf_id));
                }
            }
        }
        
        protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            DialogResult dr = MessageBox.Show("Vill du avanmäla dig?","", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); //Messegebox för medlemmen, ok eller cancel avanmäla sig
            if (dr == DialogResult.OK)
            {
                cmd.CommandText = "DELETE FROM booking_competition WHERE booking_competition.id = @competitionId";
                cmd.Parameters.AddWithValue("@competitionId", Convert.ToInt32(GridView1.Rows[e.RowIndex].Cells[1].Text));
                cmd.Connection = cn;
                cn.Open();
                int antalposter = cmd.ExecuteNonQuery();
                if (antalposter >= 1) //Meddelande ifall det gick eller inte gick att avboka
                {
                    MessageBox.Show("Du har avkokat dig från tävlingen");
                }
                else
                {
                    MessageBox.Show("Gick inte att avanmäla sig från tävlingen");
                }
                cn.Close();
                GridView1.DataSource = null; //Nollställer gridviewen innan den uppdateras
                GridView2.DataSource = null;
                loadtvl();                  //uppdaterar båda gridviewsen
                loadkommandetvl();
            }
            else if (dr == DialogResult.Cancel) //Ifall medlemmen ångrar sig kommer den tillbaka till sidan
            {
                return;
            }
         }
        
        protected void GridView2_SelectedIndexChanged(object sender, EventArgs e)
        {
            GridViewRow row = GridView2.SelectedRow;
            {
                DialogResult dr = MessageBox.Show("Vill du anmäla dig till den här tävlingen?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question); //Allt är ungefär som i gridview1 fast här anmäler medlemmen sig
                if (dr == DialogResult.Yes)
                {
                    string timestamp = DateTime.Now.ToString();
                    
                    cmd.CommandText = "INSERT INTO booking_competition(competition, player, last_update) VALUES (@competitionId, @golf_id, @timestamp)";
                    cmd.Parameters.AddWithValue("@competitionId", Convert.ToInt32(GridView2.SelectedRow.Cells[1].Text));
                    cmd.Parameters.AddWithValue("@timestamp", timestamp);
                    
                    cmd.Connection = cn;
                    cn.Open();
                    int antalposter = cmd.ExecuteNonQuery();
                    if (antalposter >= 1)
                    {
                        MessageBox.Show("Du har anmält dig till tävlingen");
                    }
                    else
                    {
                        MessageBox.Show("Gick inte att anmäla sig till tävlingen");
                    }
                    cn.Close();
                    GridView1.DataSource = null; //Nollställer gridviewen innan den uppdateras
                    GridView2.DataSource = null;
                    loadkommandetvl();
                    loadtvl();
                }
                else if (dr == DialogResult.No)
                {
                    return;
                }
            }
        }

        protected void Avboka_Click(object sender, EventArgs e)
        {
            cn.Open();
            String[] split = Regex.Split(BokadeTider.SelectedItem.ToString(), " - ");
            String date = split[0];
            String timestamp = split[1];

            NpgsqlCommand command = new NpgsqlCommand("delete from booking_play where date = '"
                + date + "' AND timestamp = '"
                + timestamp + "' AND player = '"
                + Session["usern"].ToString() + "';", cn);
            int antalposter = command.ExecuteNonQuery();
            if (antalposter == 0)
                MessageBox.Show("Bokning med id " + BokadeTider.SelectedItem.ToString() + " kunde ej tas bort");

            cn.Close();
            BokadeTider.Items.Remove(BokadeTider.SelectedItem);
        }

        protected void Logout_Click(object sender, EventArgs e)
        {
            Session.Abandon();
            Response.Redirect("Default.aspx");
        }

        protected void Tider_SelectedIndexChanged(object sender, EventArgs e)
        {
        }

        private List<string> GetOtherUsers()
        {
            List<string> users = new List<String>();
            cn.Open();
            NpgsqlCommand command = new NpgsqlCommand("SELECT golf_id FROM members where golf_id != '"
                    + Session["usern"].ToString() + "';", cn);
            NpgsqlDataReader dr = command.ExecuteReader();

            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    users.Add(dr["golf_id"].ToString());
                }
            }
            cn.Close();
            return users;
        }

        protected List<string> GetOtherUsersNotBookedOnTime(string tid)
        {
            List<string> allUsers = GetOtherUsers();
            List<string> usersBooked = new List<String>();
            List<string> usersNotBooked = new List<string>();
            cn.Open();

            String[] split = Regex.Split(tid, " ");
            String date = split[0];
            String timestamp = split[1];

            NpgsqlCommand command = new NpgsqlCommand("SELECT player FROM booking_play where date = '"
                + date + "' AND timestamp = '" + timestamp + "';", cn);
            NpgsqlDataReader dr = command.ExecuteReader();

            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    usersBooked.Add(dr["player"].ToString());
                }
            }
            cn.Close();

            foreach (string user in allUsers)
            {
                if (!usersBooked.Contains(user))
                    usersNotBooked.Add(user);
            }

            return usersNotBooked;
        }

        protected int GetBookingCount(string tid)
        {
            int count = 0;
            cn.Open();
            String[] split = Regex.Split(tid, " ");
            String date = split[0];
            String timestamp = split[1];

            NpgsqlCommand command = new NpgsqlCommand("SELECT COUNT(*) FROM booking_play where date = '"
                + date + "' AND timestamp = '" + timestamp + "';", cn);
            NpgsqlDataReader dr = command.ExecuteReader();

            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    count = Convert.ToInt32(dr["count"]);
                }
            }
            cn.Close();
            return count;
        }

        protected void bokasällskap_Click(object sender, EventArgs e)
        {
            List<DropDownList> SällskapDropDowns = new List<DropDownList>();
            SällskapDropDowns.Add(Sällskap1);
            SällskapDropDowns.Add(Sällskap2);
            SällskapDropDowns.Add(Sällskap3);

            // Spara undan redan sparade så att vi inte bokar samma två gånger
            List<string> bokade = new List<string>();

            foreach (DropDownList list in SällskapDropDowns)
            {
                if (list.Visible == true 
                    && list.SelectedItem.ToString() != "Ingen vald"
                    && !bokade.Contains(list.SelectedItem.ToString()))
                {
                    if (bokaSpelFörSpelare(list.SelectedItem.ToString(), senastBokadTid.Text))
                    {
                        bokade.Add(list.SelectedItem.ToString());
                        sällskapsinfo.Text = "Bokade sällskap";
                    }
                    else
                    {
                        sällskapsinfo.Text = "Kunde ej boka sällskap " + list.SelectedItem.ToString()
                            + " senast " + senastBokadTid.Text;
                    }
                }
            }
            UppdateraSällskapsListor();
            HideSällskap();
            Tider.Visible = false;
            bokaspel.Visible = false;
        }
    }
}